using MediatR;
using Microsoft.Extensions.Logging;
using S.M.SmartMedical.API.Write.Application.Command;
using S.M.SmartMedical.Domain.Entities;
using S.M.SmartMedical.Domain.Enums;
using S.M.SmartMedical.ErrorCode;
using S.M.SmartMedical.Infrastructure.BaseRepository;
using S.M.SmartMedical.Infrastructure;

namespace S.M.SmartMedical.API.Write.Application.Handler;

/// <summary>
/// 更新开单申请状态处理器
/// </summary>
public class UpdateOrderStatusHandler : IRequestHandler<UpdateOrderStatusCommand, APIResult<bool>>
{
    private readonly IRepository<OrderApplication> _orderRepository;
    private readonly MyDbContext _dbContext;
    private readonly ILogger<UpdateOrderStatusHandler> _logger;

    public UpdateOrderStatusHandler(
        IRepository<OrderApplication> orderRepository,
        MyDbContext dbContext,
        ILogger<UpdateOrderStatusHandler> logger)
    {
        _orderRepository = orderRepository;
        _dbContext = dbContext;
        _logger = logger;
    }

    /// <summary>
    /// 处理更新开单申请状态命令
    /// </summary>
    /// <param name="request">更新状态命令</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>更新结果</returns>
    public async Task<APIResult<bool>> Handle(UpdateOrderStatusCommand request, CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogInformation("开始更新开单申请状态，申请ID: {OrderApplicationId}, 新状态: {Status}", 
                request.OrderApplicationId, request.Status);

            // 查找开单申请
            var orderApplication = await _orderRepository.GetByIdAsync(request.OrderApplicationId);
            if (orderApplication == null)
            {
                _logger.LogWarning("未找到开单申请，ID: {OrderApplicationId}", request.OrderApplicationId);
                return new APIResult<bool>
                {
                    Code = APIEnum.Fail,
                    Message = "开单申请不存在",
                    Data = false
                };
            }

            // 权限验证：如果提供了用户ID，验证是否为申请人
            if (request.UserId.HasValue && orderApplication.UserId != request.UserId.Value)
            {
                _logger.LogWarning("用户权限不足，用户ID: {UserId}, 申请人ID: {ApplicantId}", 
                    request.UserId, orderApplication.UserId);
                return new APIResult<bool>
                {
                    Code = APIEnum.Fail,
                    Message = "无权限操作此开单申请",
                    Data = false
                };
            }

            // 状态转换验证
            if (!IsValidStatusTransition(orderApplication.Status, request.Status))
            {
                _logger.LogWarning("无效的状态转换，当前状态: {CurrentStatus}, 目标状态: {TargetStatus}", 
                    orderApplication.Status, request.Status);
                return new APIResult<bool>
                {
                    Code = APIEnum.Fail,
                    Message = $"无法从{GetStatusText(orderApplication.Status)}状态转换为{GetStatusText(request.Status)}状态",
                    Data = false
                };
            }

            // 更新状态
            orderApplication.Status = request.Status;
            orderApplication.UpdateTime = DateTime.Now;

            // 如果是支付状态，更新支付相关信息
            if (request.Status == OrderApplicationStatus.Paid)
            {
                orderApplication.PaymentMethod = request.PaymentMethod;
                orderApplication.PaymentTransactionId = request.PaymentTransactionId;
                orderApplication.PaymentTime = request.PaymentTime ?? DateTime.Now;
            }

            // 保存更改
            await _orderRepository.UpdateAsync(orderApplication);
            
            // 实际保存到数据库
            var saveResult = await _dbContext.SaveChangesAsync(cancellationToken);
            
            if (saveResult > 0)
            {
                _logger.LogInformation("成功更新开单申请状态，申请ID: {OrderApplicationId}, 新状态: {Status}", 
                    request.OrderApplicationId, request.Status);
                return new APIResult<bool>
                {
                    Code = APIEnum.OK,
                    Message = "状态更新成功",
                    Data = true
                };
            }
            else
            {
                _logger.LogError("更新开单申请状态失败，申请ID: {OrderApplicationId}", request.OrderApplicationId);
                return new APIResult<bool>
                {
                    Code = APIEnum.Fail,
                    Message = "状态更新失败",
                    Data = false
                };
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新开单申请状态时发生异常，申请ID: {OrderApplicationId}", request.OrderApplicationId);
            return new APIResult<bool>
            {
                Code = APIEnum.Fail,
                Message = "系统异常，请稍后重试",
                Data = false
            };
        }
    }

    /// <summary>
    /// 验证状态转换是否有效
    /// </summary>
    /// <param name="currentStatus">当前状态</param>
    /// <param name="targetStatus">目标状态</param>
    /// <returns>是否有效</returns>
    private static bool IsValidStatusTransition(OrderApplicationStatus currentStatus, OrderApplicationStatus targetStatus)
    {
        return currentStatus switch
        {
            OrderApplicationStatus.Draft => targetStatus == OrderApplicationStatus.Pending || 
                                          targetStatus == OrderApplicationStatus.Cancelled,
            OrderApplicationStatus.Pending => targetStatus == OrderApplicationStatus.Paid || 
                                            targetStatus == OrderApplicationStatus.Cancelled,
            OrderApplicationStatus.Paid => targetStatus == OrderApplicationStatus.Progress || 
                                         targetStatus == OrderApplicationStatus.Cancelled,
            OrderApplicationStatus.Progress => targetStatus == OrderApplicationStatus.Completed,
            OrderApplicationStatus.Completed => false, // 已完成状态不能再转换
            OrderApplicationStatus.Cancelled => false, // 已取消状态不能再转换
            _ => false
        };
    }

    /// <summary>
    /// 获取状态文本描述
    /// </summary>
    /// <param name="status">状态</param>
    /// <returns>状态文本</returns>
    private static string GetStatusText(OrderApplicationStatus status)
    {
        return status switch
        {
            OrderApplicationStatus.Draft => "草稿",
            OrderApplicationStatus.Pending => "待支付",
            OrderApplicationStatus.Paid => "已支付",
            OrderApplicationStatus.Progress => "进行中",
            OrderApplicationStatus.Completed => "已完成",
            OrderApplicationStatus.Cancelled => "已取消",
            _ => "未知状态"
        };
    }
}

/// <summary>
/// 支付开单申请处理器
/// </summary>
public class PayOrderApplicationHandler : IRequestHandler<PayOrderApplicationCommand, APIResult<PaymentResultDto>>
{
    private readonly IRepository<OrderApplication> _orderRepository;
    private readonly MyDbContext _dbContext;
    private readonly ILogger<PayOrderApplicationHandler> _logger;

    public PayOrderApplicationHandler(
        IRepository<OrderApplication> orderRepository,
        MyDbContext dbContext,
        ILogger<PayOrderApplicationHandler> logger)
    {
        _orderRepository = orderRepository;
        _dbContext = dbContext;
        _logger = logger;
    }

    /// <summary>
    /// 处理支付开单申请命令
    /// </summary>
    /// <param name="request">支付命令</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>支付结果</returns>
    public async Task<APIResult<PaymentResultDto>> Handle(PayOrderApplicationCommand request, CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogInformation("开始处理开单申请支付，申请ID: {OrderApplicationId}, 用户ID: {UserId}, 支付方式: {PaymentMethod}", 
                request.OrderApplicationId, request.UserId, request.PaymentMethod);

            // 查找开单申请
            var orderApplication = await _orderRepository.GetByIdAsync(request.OrderApplicationId);
            if (orderApplication == null)
            {
                _logger.LogWarning("未找到开单申请，ID: {OrderApplicationId}", request.OrderApplicationId);
                return new APIResult<PaymentResultDto>
                {
                    Code = APIEnum.Fail,
                    Message = "开单申请不存在",
                    Data = null
                };
            }

            // 权限验证
            if (orderApplication.UserId != request.UserId)
            {
                _logger.LogWarning("用户权限不足，用户ID: {UserId}, 申请人ID: {ApplicantId}", 
                    request.UserId, orderApplication.UserId);
                return new APIResult<PaymentResultDto>
                {
                    Code = APIEnum.Fail,
                    Message = "无权限操作此开单申请",
                    Data = null
                };
            }

            // 状态验证
            if (orderApplication.Status != OrderApplicationStatus.Pending)
            {
                _logger.LogWarning("开单申请状态不正确，当前状态: {Status}", orderApplication.Status);
                return new APIResult<PaymentResultDto>
                {
                    Code = APIEnum.Fail,
                    Message = "只有待支付状态的开单申请才能进行支付",
                    Data = null
                };
            }

            // 金额验证
            if (request.PaymentAmount != orderApplication.TotalAmount)
            {
                _logger.LogWarning("支付金额不匹配，应付金额: {TotalAmount}, 实付金额: {PaymentAmount}", 
                    orderApplication.TotalAmount, request.PaymentAmount);
                return new APIResult<PaymentResultDto>
                {
                    Code = APIEnum.Fail,
                    Message = "支付金额与订单金额不匹配",
                    Data = null
                };
            }

            // 模拟支付处理（实际项目中这里会调用第三方支付接口）
            var paymentTime = DateTime.Now;
            var transactionId = request.PaymentTransactionId ?? GenerateTransactionId();

            // 更新订单状态为已支付
            orderApplication.Status = OrderApplicationStatus.Paid;
            orderApplication.PaymentMethod = request.PaymentMethod;
            orderApplication.PaymentTransactionId = transactionId;
            orderApplication.PaymentTime = paymentTime;
            orderApplication.UpdateTime = paymentTime;

            // 保存更改
            await _orderRepository.UpdateAsync(orderApplication);
            
            // 实际保存到数据库
            var saveResult = await _dbContext.SaveChangesAsync(cancellationToken);
            
            if (saveResult > 0)
            {
                _logger.LogInformation("支付成功，申请ID: {OrderApplicationId}, 交易号: {TransactionId}", 
                    request.OrderApplicationId, transactionId);
                
                var paymentResult = new PaymentResultDto
                {
                    OrderApplicationId = orderApplication.Id,
                    ApplicationNumber = orderApplication.ApplicationNumber,
                    PaymentSuccess = true,
                    PaymentTime = paymentTime,
                    PaymentAmount = request.PaymentAmount,
                    PaymentMethod = request.PaymentMethod,
                    PaymentTransactionId = transactionId,
                    Status = OrderApplicationStatus.Paid
                };

                return new APIResult<PaymentResultDto>
                {
                    Code = APIEnum.OK,
                    Message = "支付成功",
                    Data = paymentResult
                };
            }
            else
            {
                _logger.LogError("支付处理失败，申请ID: {OrderApplicationId}", request.OrderApplicationId);
                return new APIResult<PaymentResultDto>
                {
                    Code = APIEnum.Fail,
                    Message = "支付处理失败，请稍后重试",
                    Data = null
                };
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "处理支付时发生异常，申请ID: {OrderApplicationId}", request.OrderApplicationId);
            return new APIResult<PaymentResultDto>
            {
                Code = APIEnum.Fail,
                Message = "系统异常，请稍后重试",
                Data = null
            };
        }
    }

    /// <summary>
    /// 生成交易号
    /// </summary>
    /// <returns>交易号</returns>
    private static string GenerateTransactionId()
    {
        return $"TXN{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}";
    }
}